"""
pytest配置文件和共享fixtures

提供测试中常用的数据对象和配置。
"""

import pytest
import pandas as pd
from datetime import date, datetime
from pathlib import Path
import tempfile
import shutil
from typing import List, Dict, Any

# 添加src路径以便导入模块
import sys
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

from models.project import Project, ProjectPriority, ProjectStatus
from models.resource import Resource, ResourceRole, SkillLevel
from models.task import Task, TaskPriority, TaskStatus


@pytest.fixture(scope="session")
def test_data_dir():
    """测试数据目录路径"""
    return Path(__file__).parent / "test_data"


@pytest.fixture(scope="session")
def temp_dir():
    """临时目录fixture，测试结束后自动清理"""
    temp_path = tempfile.mkdtemp()
    yield Path(temp_path)
    shutil.rmtree(temp_path)


@pytest.fixture
def sample_projects() -> List[Project]:
    """示例项目数据"""
    return [
        Project(
            project_id="P001",
            project_name="新ECサイト开发",
            start_date=date(2024, 1, 1),
            end_date=date(2024, 6, 30),
            priority=ProjectPriority.HIGH,
            status=ProjectStatus.PLANNING,
            description="新电商网站开发项目"
        ),
        Project(
            project_id="P002",
            project_name="基础系统优化",
            start_date=date(2024, 3, 1),
            end_date=date(2024, 8, 31),
            priority=ProjectPriority.MEDIUM,
            status=ProjectStatus.IN_PROGRESS,
            description="基础系统性能优化项目"
        ),
        Project(
            project_id="P003",
            project_name="移动APP开发",
            start_date=date(2024, 5, 1),
            end_date=date(2024, 12, 31),
            priority=ProjectPriority.HIGH,
            status=ProjectStatus.PLANNING,
            description="移动端应用开发项目"
        )
    ]


@pytest.fixture
def sample_resources() -> List[Resource]:
    """示例资源数据"""
    return [
        Resource(
            resource_id="R001",
            name="田中太郎",
            role=ResourceRole.PROJECT_MANAGER,
            skill_level=SkillLevel.SENIOR,
            max_hours_per_week=40,
            available_from=date(2024, 1, 1),
            available_to=date(2024, 12, 31),
            hourly_rate=5000,
            skills={"プロジェクト管理", "チーム管理", "予算管理"},
            department="プロジェクト推進部"
        ),
        Resource(
            resource_id="R002",
            name="佐藤花子",
            role=ResourceRole.SYSTEM_ENGINEER,
            skill_level=SkillLevel.SENIOR,
            max_hours_per_week=40,
            available_from=date(2024, 1, 1),
            available_to=date(2024, 12, 31),
            hourly_rate=4000,
            skills={"Java", "Spring", "AWS", "データベース設計"},
            department="開発部"
        ),
        Resource(
            resource_id="R003",
            name="鈴木一郎",
            role=ResourceRole.PROGRAMMER,
            skill_level=SkillLevel.INTERMEDIATE,
            max_hours_per_week=40,
            available_from=date(2024, 1, 1),
            available_to=date(2024, 12, 31),
            hourly_rate=3000,
            skills={"JavaScript", "React", "Node.js", "HTML/CSS"},
            department="開発部"
        ),
        Resource(
            resource_id="R004",
            name="高橋美緒",
            role=ResourceRole.TESTER,
            skill_level=SkillLevel.INTERMEDIATE,
            max_hours_per_week=40,
            available_from=date(2024, 1, 1),
            available_to=date(2024, 12, 31),
            hourly_rate=2500,
            skills={"テスト計画", "自動テスト", "Selenium", "性能テスト"},
            department="品質保証部"
        ),
        Resource(
            resource_id="R005",
            name="山田次郎",
            role=ResourceRole.PROGRAMMER,
            skill_level=SkillLevel.JUNIOR,
            max_hours_per_week=40,
            available_from=date(2024, 1, 1),
            available_to=date(2024, 12, 31),
            hourly_rate=2000,
            skills={"Python", "Django", "PostgreSQL"},
            department="開発部"
        )
    ]


@pytest.fixture
def sample_tasks() -> List[Task]:
    """示例任务数据"""
    return [
        Task(
            task_id="T001",
            project_id="P001",
            task_name="プロジェクト計画策定",
            required_role=ResourceRole.PROJECT_MANAGER,
            required_skill_level=SkillLevel.SENIOR,
            estimated_hours=80,
            start_date=date(2024, 1, 1),
            end_date=date(2024, 1, 31),
            priority=TaskPriority.VERY_HIGH,
            required_skills={"プロジェクト管理"},
            description="プロジェクト全体の計画を策定"
        ),
        Task(
            task_id="T002",
            project_id="P001",
            task_name="要件定義・設計",
            required_role=ResourceRole.SYSTEM_ENGINEER,
            required_skill_level=SkillLevel.SENIOR,
            estimated_hours=160,
            start_date=date(2024, 2, 1),
            end_date=date(2024, 3, 31),
            priority=TaskPriority.HIGH,
            required_skills={"システム設計", "要件定義"},
            dependency_tasks=["T001"],
            description="システムの要件定義と基本設計"
        ),
        Task(
            task_id="T003",
            project_id="P001",
            task_name="フロントエンド開発",
            required_role=ResourceRole.PROGRAMMER,
            required_skill_level=SkillLevel.INTERMEDIATE,
            estimated_hours=240,
            start_date=date(2024, 4, 1),
            end_date=date(2024, 5, 31),
            priority=TaskPriority.HIGH,
            required_skills={"JavaScript", "React"},
            dependency_tasks=["T002"],
            description="フロントエンドユーザーインターフェース開発"
        ),
        Task(
            task_id="T004",
            project_id="P001",
            task_name="システムテスト",
            required_role=ResourceRole.TESTER,
            required_skill_level=SkillLevel.INTERMEDIATE,
            estimated_hours=120,
            start_date=date(2024, 6, 1),
            end_date=date(2024, 6, 30),
            priority=TaskPriority.HIGH,
            required_skills={"テスト計画", "自動テスト"},
            dependency_tasks=["T003"],
            description="総合テストとバグ修正"
        ),
        Task(
            task_id="T005",
            project_id="P002",
            task_name="パフォーマンス分析",
            required_role=ResourceRole.SYSTEM_ENGINEER,
            required_skill_level=SkillLevel.SENIOR,
            estimated_hours=100,
            start_date=date(2024, 3, 1),
            end_date=date(2024, 4, 30),
            priority=TaskPriority.MEDIUM,
            required_skills={"パフォーマンス分析", "データベース"},
            description="既存システムのパフォーマンス問題分析"
        )
    ]


@pytest.fixture
def sample_excel_data():
    """示例Excel数据格式"""
    project_info = {
        'project_name': '新ECサイト开发',
        'start_year_month': '2024-01',
        'end_year_month': '2024-06'
    }
    
    project_roles = [
        {'role': 'PM', 'unit_price': 500000, 'total_cost': 1000000},
        {'role': 'SE', 'unit_price': 400000, 'total_cost': 1600000},
        {'role': 'PG', 'unit_price': 300000, 'total_cost': 1200000},
        {'role': 'テスター', 'unit_price': 250000, 'total_cost': 500000}
    ]
    
    phases_detail = [
        {
            'phase_id': 'P001',
            'phase_name': '計画フェーズ',
            'start_year_month': '2024-01',
            'end_year_month': '2024-01',
            'role': 'PM',
            'person_months': 2.0,
            'unit_price': 500000,
            'total_cost': 1000000
        },
        {
            'phase_id': 'P002',
            'phase_name': '設計フェーズ',
            'start_year_month': '2024-02',
            'end_year_month': '2024-03',
            'role': 'SE',
            'person_months': 4.0,
            'unit_price': 400000,
            'total_cost': 1600000
        },
        {
            'phase_id': 'P003',
            'phase_name': '開発フェーズ',
            'start_year_month': '2024-04',
            'end_year_month': '2024-05',
            'role': 'PG',
            'person_months': 4.0,
            'unit_price': 300000,
            'total_cost': 1200000
        },
        {
            'phase_id': 'P004',
            'phase_name': 'テストフェーズ',
            'start_year_month': '2024-06',
            'end_year_month': '2024-06',
            'role': 'テスター',
            'person_months': 2.0,
            'unit_price': 250000,
            'total_cost': 500000
        }
    ]
    
    return {
        'project_info': project_info,
        'project_roles': project_roles,
        'phases_detail': phases_detail
    }


@pytest.fixture
def invalid_excel_data():
    """无效的Excel数据（用于测试验证功能）"""
    return {
        'project_info': {
            'project_name': '',  # 空项目名称
            'start_year_month': '2024/01',  # 错误的日期格式
            'end_year_month': '2023-12'  # 结束时间早于开始时间
        },
        'project_roles': [
            {'role': 'INVALID_ROLE', 'unit_price': -1000}  # 无效角色和负单价
        ],
        'phases_detail': [
            {
                'phase_id': 'P001',
                'phase_name': '',  # 空阶段名称
                'start_year_month': '2024-01',
                'end_year_month': '2024-12',
                'role': 'UNDEFINED_ROLE',  # 未定义的角色
                'total_cost': -5000  # 负成本
            }
        ]
    }


@pytest.fixture
def missing_roles_data():
    """缺少角色的测试数据"""
    return {
        'project_info': {
            'project_name': '缺少角色的项目',
            'start_year_month': '2024-01',
            'end_year_month': '2024-06'
        },
        'project_roles': [
            {'role': 'PM', 'unit_price': 500000, 'total_cost': 1000000},
            # 缺少SE角色定义
        ],
        'phases_detail': [
            {
                'phase_id': 'P001',
                'phase_name': '計画フェーズ',
                'start_year_month': '2024-01',
                'end_year_month': '2024-01',
                'role': 'PM',
                'person_months': 2.0,
                'unit_price': 500000,
                'total_cost': 1000000
            },
            {
                'phase_id': 'P002',
                'phase_name': '設計フェーズ',
                'start_year_month': '2024-02',
                'end_year_month': '2024-03',
                'role': 'SE',  # 未在project_roles中定义
                'person_months': 4.0,
                'unit_price': 400000,
                'total_cost': 1600000
            }
        ]
    }


@pytest.fixture
def edge_case_data():
    """边界情况测试数据"""
    return {
        'project_info': {
            'project_name': '边界测试项目',
            'start_year_month': '2024-01',
            'end_year_month': '2027-01'  # 超过36个月
        },
        'project_roles': [
            {'role': 'PM', 'unit_price': 50000, 'total_cost': 100000},  # 低单价
            {'role': 'SE', 'unit_price': 6000000, 'total_cost': 12000000}  # 高单价
        ],
        'phases_detail': [
            {
                'phase_id': 'P001',
                'phase_name': '短期阶段',
                'start_year_month': '2024-01',
                'end_year_month': '2024-01',
                'role': 'PM',
                'person_months': 0.05,  # 极小人月数
                'unit_price': 50000,
                'total_cost': 2500
            },
            {
                'phase_id': 'P002',
                'phase_name': '高成本阶段',
                'start_year_month': '2024-02',
                'end_year_month': '2024-02',
                'role': 'SE',
                'person_months': 2.0,
                'unit_price': 6000000,
                'total_cost': 12000000
            }
        ]
    }


# 辅助函数
def create_test_excel_file(data: Dict[str, Any], file_path: Path) -> None:
    """创建测试用的Excel文件"""
    with pd.ExcelWriter(file_path, engine='openpyxl') as writer:
        # 创建project_info工作表
        if 'project_info' in data:
            project_df = pd.DataFrame([data['project_info']])
            project_df.to_excel(writer, sheet_name='project_info', index=False)
        
        # 创建project_roles工作表
        if 'project_roles' in data:
            roles_df = pd.DataFrame(data['project_roles'])
            roles_df.to_excel(writer, sheet_name='project_roles', index=False)
        
        # 创建phases_detail工作表
        if 'phases_detail' in data:
            phases_df = pd.DataFrame(data['phases_detail'])
            phases_df.to_excel(writer, sheet_name='phases_detail', index=False)


def create_test_data_files(data_dir: Path, projects: List[Project], 
                          resources: List[Resource], tasks: List[Task]) -> None:
    """创建测试数据文件"""
    # 创建项目数据文件
    projects_data = []
    for project in projects:
        projects_data.append({
            'project_id': project.project_id,
            'project_name': project.project_name,
            'start_date': project.start_date,
            'end_date': project.end_date,
            'priority': project.priority.value,
            'status': project.status.value,
            'description': project.description
        })
    
    projects_df = pd.DataFrame(projects_data)
    projects_df.to_excel(data_dir / 'projects.xlsx', index=False)
    
    # 创建资源数据文件
    resources_data = []
    for resource in resources:
        resources_data.append({
            'resource_id': resource.resource_id,
            'name': resource.name,
            'role': resource.role.value,
            'skill_level': resource.skill_level.value,
            'max_hours_per_week': resource.max_hours_per_week,
            'available_from': resource.available_from,
            'available_to': resource.available_to,
            'hourly_rate': resource.hourly_rate,
            'skills': ','.join(resource.skills),
            'department': resource.department
        })
    
    resources_df = pd.DataFrame(resources_data)
    resources_df.to_excel(data_dir / 'resources.xlsx', index=False)
    
    # 创建任务数据文件
    tasks_data = []
    for task in tasks:
        tasks_data.append({
            'task_id': task.task_id,
            'project_id': task.project_id,
            'task_name': task.task_name,
            'required_role': task.required_role.value,
            'required_skill_level': task.required_skill_level.value,
            'estimated_hours': task.estimated_hours,
            'start_date': task.start_date,
            'end_date': task.end_date,
            'dependency_tasks': ','.join(task.dependency_tasks),
            'priority': task.priority.value,
            'required_skills': ','.join(task.required_skills),
            'status': task.status.value,
            'description': task.description
        })
    
    tasks_df = pd.DataFrame(tasks_data)
    tasks_df.to_excel(data_dir / 'tasks.xlsx', index=False)